package domain

import (
	"context"
	"errors"
	"exchange/internal/dao"
	"exchange/internal/model"
	"exchange/internal/repo"
	"grpc-common/market/mclient"
	"grpc-common/ucenter/ucclient"
	"mscoin-common/msdb"
	"mscoin-common/op"
	"mscoin-common/tools"
	"time"
)

type ExchangeOrderDomain struct {
	orderRepo repo.ExchangeOrderRepo
}

func NewExchangeOrderDomain(db *msdb.MsDB) *ExchangeOrderDomain {
	return &ExchangeOrderDomain{
		orderRepo: dao.NewExchangeOrderDao(db),
	}
}

// 查看历史订单
func (e *ExchangeOrderDomain) FindOrderHistory(ctx context.Context, symbol string, page int64, size int64, memberId int64) ([]*model.ExchangeOrderVo, int64, error) {
	list, total, err := e.orderRepo.FindOrderHistory(ctx, symbol, page, size, memberId)
	if err != nil {
		return nil, 0, err
	}
	if total == 0 {
		return nil, 0, err
	}
	voList := make([]*model.ExchangeOrderVo, len(list))
	for i, v := range list {
		voList[i] = v.ToVo()
	}
	return voList, total, nil
}

// 查看当前交易订单
func (e *ExchangeOrderDomain) FindOrderCurrent(ctx context.Context, symbol string, page int64, size int64, memberId int64) ([]*model.ExchangeOrderVo, int64, error) {
	list, total, err := e.orderRepo.FindOrderCurrent(ctx, symbol, page, size, memberId)
	if err != nil {
		return nil, 0, err
	}
	if total == 0 {
		return nil, 0, err
	}
	voList := make([]*model.ExchangeOrderVo, len(list))
	for i, v := range list {
		voList[i] = v.ToVo()
	}
	return voList, total, nil
}

func (e *ExchangeOrderDomain) FindCurrentTradingCount(ctx context.Context, id int64, symbol string, direction string) (int64, error) {
	count, err := e.orderRepo.FindCurrentTradingCount(ctx, id, symbol, model.DirectionMap.Code(direction))
	return count, err
}

func (e *ExchangeOrderDomain) Save(ctx context.Context, conn msdb.DbConn, order *model.ExchangeOrder) error {
	err := e.orderRepo.Save(ctx, conn, order)
	return err
}

// 根据订单id查询交易订单
// select * from exchange_order where order_id = order_id
func (e *ExchangeOrderDomain) FindOrderByOrderId(ctx context.Context, orderId string) (*model.ExchangeOrder, error) {
	order, err := e.orderRepo.FindOrderByOrderId(ctx, orderId)
	return order, err
}

// 修改订单的状态为取消状态
func (e *ExchangeOrderDomain) UpdateStatusCancel(ctx context.Context, orderId string) error {
	return e.orderRepo.UpdateStatusCancel(ctx, orderId)
}

// 修改订单的状态为正在交易的状态0
func (e *ExchangeOrderDomain) UpdateOrderStatusTrading(ctx context.Context, orderId string) error {
	return e.orderRepo.UpdateOrderStatusTrading(ctx, orderId)
}

// 委托订单入库
func (e *ExchangeOrderDomain) AddOrder(ctx context.Context, conn msdb.DbConn, order *model.ExchangeOrder, coin *mclient.ExchangeCoin, baseWallet *ucclient.MemberWallet, coinWallet *ucclient.MemberWallet) (float64, error) {
	order.Status = model.Init //初始状态
	order.TradedAmount = 0
	order.Time = time.Now().UnixMilli()
	order.OrderId = tools.Unq("E")
	//交易的时候暂时不考虑手续费
	var money float64
	if order.Direction == model.BUY {
		if order.Type == model.MarketPrice {
			//暂时无法确定价格，先锁定数量
			money = order.Amount
		} else {
			money = op.FloorFloat(order.Price*order.Amount, 8)
		}
		if baseWallet.Balance < money {
			return 0, errors.New("基准币余额不足")
		}
	} else {
		//是卖的话，直接冻结的是数量
		money = order.Amount
		if coinWallet.Balance < money {
			return 0, errors.New("交易币余额不足")
		}
	}
	//save order
	err := e.orderRepo.Save(ctx, conn, order)
	return money, err
}
